package com.lcy.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.lcy.exception.BusinessException;
import com.lcy.mapper.OjProblemMapper;
import com.lcy.mapper.ProblemCommentMapper;
import com.lcy.mapstruct.ProblemCommentMapstruct;
import com.lcy.model.dto.problemComment.ProblemCommentRequest;
import com.lcy.model.entity.ProblemComment;
import com.lcy.model.vo.ProblemCommentVo;
import com.lcy.security.utils.SecurityHelper;
import com.lcy.service.ProblemCommentService;
import com.lcy.sys.mapper.SysUserMapper;
import com.lcy.sys.model.entity.SysUser;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import static com.lcy.model.entity.table.OjProblemTableDef.OJ_PROBLEM;
import static com.lcy.model.entity.table.ProblemCommentTableDef.PROBLEM_COMMENT;
import static com.lcy.sys.model.entity.table.SysUserTableDef.SYS_USER;

/**
 * 题目评论 服务层实现。
 *
 * @author zhang.rx
 * @since 2024/4/18
 */
@Service
public class ProblemCommentServiceImpl extends ServiceImpl<ProblemCommentMapper, ProblemComment>
		implements ProblemCommentService {

	@Resource
	private ProblemCommentMapstruct commentMapstruct;

	@Resource
	private SysUserMapper userMapper;

	@Resource
	private OjProblemMapper problemMapper;

	@Resource
	private ProblemCommentMapper commentMapper;

	@Override
	public Boolean save(ProblemCommentRequest req) {
		SysUser user = SecurityHelper.getUser();
		long count = problemMapper
			.selectCountByCondition(OJ_PROBLEM.ID.eq(req.getProblemId(), req.getProblemId() != null));
		if (count == 0) {
			throw new BusinessException("题目不存在");
		}
		ProblemComment entity = commentMapstruct.toEntity(req);
		entity.setAuthorId(user.getId());
		return save(entity);
	}

	@Override
	@Transactional(readOnly = true)
	public List<ProblemCommentVo> list(Long problemId) {
//		QueryWrapper queryWrapper = new QueryWrapper()
//			.where(PROBLEM_COMMENT.PROBLEM_ID.eq(problemId, problemId != null))
//			.and(PROBLEM_COMMENT.PARENT_ID.isNull());
//		List<ProblemComment> problemComments = commentMapper.selectListByQuery(queryWrapper);
//		List<ProblemCommentVo> voList = commentMapstruct.toVoList(problemComments);
//		Set<Long> userIds = Sets.newHashSet();
////		// 查询所有子节点
////		voList.forEach(e -> findChildren(e, userIds));
////		findUserInfo(voList, userIds);
////		return voList;
//		// 使用非递归方式查询所有子节点
//		voList.forEach(e -> findChildren(e, userIds));
//		findUserInfo(voList, userIds);
//		return voList;

		// 1. 一次性查询所有顶级评论及其用户信息
//		QueryWrapper topCommentsQuery = new QueryWrapper()
//				.where(PROBLEM_COMMENT.PROBLEM_ID.eq(problemId))
//				.and(PROBLEM_COMMENT.PARENT_ID.isNull())
//				.leftJoin(SYS_USER).on(PROBLEM_COMMENT.AUTHOR_ID.eq(SYS_USER.ID))
//				.select(PROBLEM_COMMENT.ALL_COLUMNS,
//						SYS_USER.NICK_NAME.as("authorName"),
//						SYS_USER.AVATAR.as("authorAvatar"));
//
//		List<ProblemComment> topComments = commentMapper.selectListByQuery(topCommentsQuery);
//		List<ProblemCommentVo> voList = commentMapstruct.toVoList(topComments);
//
//		// 2. 一次性查询所有子评论
//		Set<Long> parentIds = voList.stream().map(ProblemCommentVo::getId).collect(Collectors.toSet());
//		if (!parentIds.isEmpty()) {
//			Map<Long, List<ProblemCommentVo>> childrenMap = findAllChildren(problemId, parentIds);
//			voList.forEach(vo -> vo.setChildren(childrenMap.getOrDefault(vo.getId(), Collections.emptyList())));
//		}
//
//		return voList;

		// 1. 一次性查询所有评论及其用户信息（包括顶级和子评论）
		QueryWrapper query = new QueryWrapper()
				.where(PROBLEM_COMMENT.PROBLEM_ID.eq(problemId))
				.leftJoin(SYS_USER).on(PROBLEM_COMMENT.AUTHOR_ID.eq(SYS_USER.ID))
				.select(PROBLEM_COMMENT.ALL_COLUMNS,
						SYS_USER.NICK_NAME.as("authorName"),
						SYS_USER.AVATAR.as("authorAvatar"));

		List<ProblemComment> allComments = commentMapper.selectListByQuery(query);
		List<ProblemCommentVo> allVos = commentMapstruct.toVoList(allComments);

		// 2. 构建评论树
		return buildCommentTree(allVos);
	}

	/**
	 * 构建评论树结构
	 */
	private List<ProblemCommentVo> buildCommentTree(List<ProblemCommentVo> allVos) {
		// 按parentId分组
		Map<Long, List<ProblemCommentVo>> childrenMap = allVos.stream()
				.filter(vo -> vo.getParentId() != null)
				.collect(Collectors.groupingBy(
						ProblemCommentVo::getParentId,
						HashMap::new,  // 指定Map类型
						Collectors.toList()
				));

		// 构建树
		List<ProblemCommentVo> rootComments = allVos.stream()
				.filter(vo -> vo.getParentId() == null)
				.collect(Collectors.toList());

		rootComments.forEach(vo -> populateChildren(vo, childrenMap));
		return rootComments;
	}

	/**
	 * 递归填充子评论
	 */
	private void populateChildren(ProblemCommentVo parent, Map<Long, List<ProblemCommentVo>> childrenMap) {
		List<ProblemCommentVo> children = childrenMap.get(parent.getId());
		if (children != null && !children.isEmpty()) {
			parent.setChildren(children);
			children.forEach(child -> populateChildren(child, childrenMap));
		} else {
			parent.setChildren(Collections.emptyList());
		}
	}


	/**
	 * 批量查询所有子评论
	 */
	private Map<Long, List<ProblemCommentVo>> findAllChildren(Long problemId, Set<Long> parentIds) {
		// 1. 查询所有子评论及其用户信息
		QueryWrapper childrenQuery = new QueryWrapper()
				.where(PROBLEM_COMMENT.PROBLEM_ID.eq(problemId))
				.and(PROBLEM_COMMENT.PARENT_ID.in(parentIds))
				.leftJoin(SYS_USER).on(PROBLEM_COMMENT.AUTHOR_ID.eq(SYS_USER.ID))
				.select(PROBLEM_COMMENT.ALL_COLUMNS,
						SYS_USER.NICK_NAME.as("authorName"),
						SYS_USER.AVATAR.as("authorAvatar"));

		List<ProblemComment> children = commentMapper.selectListByQuery(childrenQuery);
		List<ProblemCommentVo> childVos = commentMapstruct.toVoList(children);

		// 2. 按父ID分组
		return childVos.stream()
				.collect(Collectors.groupingBy(ProblemCommentVo::getParentId));
	}

	@Override
	@Transactional(readOnly = true)
	public List<ProblemCommentVo> listChildren(Long parentId) {
//		QueryWrapper queryWrapper = new QueryWrapper().where(PROBLEM_COMMENT.PARENT_ID.eq(parentId, parentId != null));
//		List<ProblemComment> problemComments = commentMapper.selectListByQuery(queryWrapper);
//		Set<Long> userIds = problemComments.stream().map(ProblemComment::getAuthorId).collect(Collectors.toSet());
//		List<ProblemCommentVo> voList = commentMapstruct.toVoList(problemComments);
//		findUserInfo(voList, userIds);
//		return voList;

		QueryWrapper queryWrapper = new QueryWrapper()
				.where(PROBLEM_COMMENT.PARENT_ID.eq(parentId))
				.leftJoin(SYS_USER).on(PROBLEM_COMMENT.AUTHOR_ID.eq(SYS_USER.ID))
				.select(PROBLEM_COMMENT.ALL_COLUMNS,
						SYS_USER.NICK_NAME.as("authorName"),
						SYS_USER.AVATAR.as("authorAvatar"));

		List<ProblemComment> comments = commentMapper.selectListByQuery(queryWrapper);
		return commentMapstruct.toVoList(comments);
	}

	/**
	 * 获取用户信息
	 */
	private void findUserInfo(List<ProblemCommentVo> voList, Set<Long> userIds) {
		List<SysUser> sysUsers = userMapper.selectListByCondition(SYS_USER.ID.in(userIds));
		setUserInfo(voList, sysUsers);
	}

	/**
	 * 递归set用户信息
	 */
	private void setUserInfo(List<ProblemCommentVo> voList, List<SysUser> sysUsers) {
		if (CollUtil.isNotEmpty(voList)) {
			voList.forEach(item -> {
				SysUser sysUser = sysUsers.stream().filter(e -> e.getId().equals(item.getAuthorId())).findFirst().get();
				item.setAuthorName(sysUser.getNickName());
				item.setAuthorAvatar(sysUser.getAvatar());
				setUserInfo(item.getChildren(), sysUsers);
			});
		}
	}

	/**
	 * 递归查询子节点
	 */
//	private void findChildren(ProblemCommentVo e, Set<Long> userIds) {
//		userIds.add(e.getAuthorId());
//		List<ProblemComment> list = QueryChain.of(commentMapper).where(PROBLEM_COMMENT.PARENT_ID.eq(e.getId())).list();
//		if (CollUtil.isEmpty(list)) {
//			return;
//		}
//		e.setChildren(commentMapstruct.toVoList(list));
//		e.getChildren().forEach(child -> findChildren(child, userIds));
//	}

	/**
	 * 使用队列实现非递归方式查询所有子节点
	 */
//	private void findChildren(ProblemCommentVo root, Set<Long> userIds) {
//		Queue<ProblemCommentVo> queue = new LinkedList<>();
//		queue.offer(root);
//
//		while (!queue.isEmpty()) {
//			ProblemCommentVo current = queue.poll();
//			userIds.add(current.getAuthorId());
//
//			List<ProblemComment> children = QueryChain.of(commentMapper)
//					.where(PROBLEM_COMMENT.PARENT_ID.eq(current.getId()))
//					.list();
//
//			if (CollUtil.isNotEmpty(children)) {
//				List<ProblemCommentVo> childVos = commentMapstruct.toVoList(children);
//				current.setChildren(childVos);
//				childVos.forEach(queue::offer);
//			}
//		}
//	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeRecursionById(Serializable id) {
		removeById(id);
		removeChildren(id);
		return true;
	}

	private void removeChildren(Serializable parentId) {
		List<Long> childrenIds = QueryChain.of(commentMapper)
			.select(PROBLEM_COMMENT.ID)
			.where(PROBLEM_COMMENT.PARENT_ID.eq(parentId))
			.listAs(Long.class);
		for (Long childrenId : childrenIds) {
			removeById(childrenId);
			removeChildren(childrenId);
		}
	}

}
